/******************************************************************************
 cnome: A C++ source "genes" discover. :-)

 See more details at:

   http://www.codeplex.com/cnome

 The original author site is at: http://www.alexandre-barbosa.com/

 Copyright (c) 2008 Alexandre Barbosa.
 Distributed under the MIT License. (See accompanying file LICENSE-MIT.txt 
 or at http://www.codeplex.com/cnome/license)
 ******************************************************************************/

#ifndef DIRECTIVE_LOOKAHEAD_HPP
#define DIRECTIVE_LOOKAHEAD_HPP

#include <boost/spirit/home/classic/core/parser.hpp>
#include <boost/spirit/home/classic/core/composite/composite.hpp>
#include <boost/spirit/home/classic/dynamic/impl/conditions.ipp>

#include "directive_base.h"
#include "variables.h"

namespace cnome { namespace directive {

    struct lookahead_parser_gen;

    template <typename ParserT>
    struct lookahead
    :   public boost::spirit::classic::unary<ParserT, boost::spirit::classic::parser<lookahead<ParserT> > >
    {
        typedef lookahead<ParserT>              self_t;
        typedef boost::spirit::classic::unary_parser_category           parser_category_t;
        typedef lookahead_parser_gen            parser_generator_t;
        typedef boost::spirit::classic::unary<ParserT, boost::spirit::classic::parser<self_t> > base_t;

        lookahead(ParserT const& p)
        : base_t(p), m_pSave(0) {}

        ~lookahead() { delete m_pSave; }

        template <typename ScannerT>
        typename boost::spirit::classic::parser_result<self_t, ScannerT>::type
        parse(ScannerT const& scan) const
        {
            typedef typename boost::spirit::classic::parser_result<self_t, ScannerT>::type result_t;
            return impl::drt_parser_parse<result_t>
                (*this, scan, scan);
        }

        const char* MyName() const { return "lookahead"; }

        template <typename ScannerT>
        inline void
        deriv_action_before_parse(
            ScannerT const& scan) const
        {
            if (!m_pSave)
                m_pSave = static_cast<void*>(new typename ScannerT::iterator_t);
            *static_cast<typename ScannerT::iterator_t*>(m_pSave) = scan.first;
            sglLookahead::instance()->set_is_looking(true);
        }

        template <typename ScannerT>
        inline void
        deriv_action_after_parse(
            ScannerT const& scan) const 
        {
            scan.first = *static_cast<typename ScannerT::iterator_t*>(m_pSave);
            sglLookahead::instance()->set_is_looking(false);
        }
        
    private:
        mutable void* m_pSave;
    };

    /*
    template <typename ParserT>
    inline lookahead<ParserT>
    operator~(lookahead<ParserT> const& p)
    {
        return p;//negated_char_parser<ParserT>(p.derived());
    }
    */

    const drt_parser_gen<lookahead> lookahead_d = drt_parser_gen<lookahead>();

}} // namespace cnome { namespace directive {

#endif

